package com.alibaba.citrus.cr.mn.order.center.facade.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.citrus.cr.common.annotation.FacadeInvoker;
import com.alibaba.citrus.cr.common.constant.OrderFeaturesKey;
import com.alibaba.citrus.cr.common.enums.ordercenter.AsyncMessageEventEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.InnerMessageEventEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.OrderCategoryEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.SalesOrderPushStatusEnum;
import com.alibaba.citrus.cr.common.lock.SaleRedisLock;
import com.alibaba.citrus.cr.mn.order.center.common.util.AssertUtils;
import com.alibaba.citrus.cr.mn.order.center.common.util.StopWatchUtils;
import com.alibaba.citrus.cr.mn.order.center.common.util.TrimUtils;
import com.alibaba.citrus.cr.mn.order.center.facade.function.asynctask.AsyncTaskCreateService;
import com.alibaba.citrus.cr.mn.order.center.facade.function.check.AbstractOrderParamsCheckService;
import com.alibaba.citrus.cr.mn.order.center.facade.function.common.*;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.crb2btradecenter.model.enums.MessageTaskTypeEnum;
import com.epoch.app.mnordercenter.model.dto.*;
import com.epoch.app.mnordercenter.orderbaserequest.*;
import com.epoch.app.mnordercenter.salesorderdirect.service.SalesOrderDirectService;
import com.google.common.collect.Lists;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import static com.alibaba.citrus.cr.mn.order.center.common.constants.RedisLockConstants.*;

/**
 * @author dongju
 * @date 2024/02/19 11:56
 */
@Service
@Primary
public class SalesOrderDirectServiceImpl implements SalesOrderDirectService {

    private static final Log log = Log.getLogger(SalesOrderDirectServiceImpl.class);

    @Resource(name = "salesOrderBizCreateService")
    private OrderBizCreateService<SalesOrderBizBatchCreateRequest, SalesOrderAtomBatchCreateRequest, OrderAtomCreateResponse> salesOrderBizCreateService;
    @Resource(name = "salesOrderBizSubmitService")
    private OrderBizSubmitService salesOrderBizSubmitService;
    @Resource(name = "salesOrderAtomCancelService")
    private OrderAtomCancelService selesOrderAtomCancelService;
    @Resource(name = "salesOrderBizUpdateService")
    private OrderBizUpdateService<OrderBizUpdateRequest, OrderAtomUpdateRequest, OrderAtomUpdateResponse> salesOrderBizUpdateService;
    @Resource(name = "salesOrderGroupCloseService")
    private OrderBizCloseService salesOrderGroupCloseService;
    @Resource
    private AsyncTaskCreateService asyncTaskCreateService;
    @Resource(name = "salesOrderDirectBizCreateParamsCheck")
    private AbstractOrderParamsCheckService salesOrderDirectBizCreateParamsCheck;
    @Resource
    private SendMsgService sendMsgService;

    @FacadeInvoker(value = "一盘货销售订单创建", errorCode = "OC-01-001-01-16-006")
    @Override
    public Result<OrderAtomCreateResponse> create(SalesOrderBizCreateRequest request) {
        AssertUtils.isTrue(StringUtils.isBlank(request.getReqNo()), "OC-01-001-01-15-001", "请求编码");
        log.info("SalesOrderDirectServiceImpl#create request={}", JSON.toJSONString(request));
        String lockKey = SALES_ORDER_DIRECT_PREFIX + request.getReqNo();
        log.info("SalesOrderDirectServiceImpl#create lockKey={}", lockKey);
        try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!lock.lock()) {
                log.error("SalesOrderDirectServiceImpl#create 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }

            // 移除入参里的前后空格
            StopWatchUtils.start("订单中心直发订单创建", "removeSpace");
            TrimUtils.removeSpace(request);
            StopWatchUtils.stop();

            StopWatchUtils.start("订单中心直发订单创建", "paramsInvalidCheck");
            AssertUtils.lengthCheck(request.getReqNo(), 128, true, "OC-01-001-01-15-004", "请求编码");
            if (ObjectUtil.isNull(request.getIsSubmit())) {
                request.setIsSubmit(Boolean.TRUE);
            }
            if (ObjectUtil.isNull(request.getCheckCreditB())) {
                request.setCheckCreditB(Boolean.TRUE);
            }
            if (ObjectUtil.isNull(request.getCheckCredit())) {
                request.setCheckCredit(Boolean.TRUE);
            }
            if (ObjectUtil.isNull(request.getCheckStock())) {
                request.setCheckStock(Boolean.TRUE);
            }

            // 设置默认值
            request.setOrderCategoryCode(OrderCategoryEnum.STOCK.getCode());
            salesOrderDirectBizCreateParamsCheck.paramsInvalidCheck(Lists.newArrayList(request), new ArrayList<>());
            StopWatchUtils.stop();

            StopWatchUtils.start("订单中心直发订单创建", "createAsyncTask");
            SalesOrderBizBatchCreateRequest createRequest = new SalesOrderBizBatchCreateRequest();
            createRequest.setReqNo(request.getReqNo());
            createRequest.setBusinessType(request.getBusinessType());
            createRequest.setBusinessUnitCode(request.getBusinessUnitCode());
            createRequest.setFromSys(request.getFromSys());
            createRequest.setOrderList(Lists.newArrayList(request));
            List<OrderAtomCreateResponse> bizCreateResponses = salesOrderBizCreateService.batchCreate(createRequest);
            StopWatchUtils.stop();

            // 发送消息释放活动预占
            OrderAtomCreateResponse orderAtomCreateResponse = bizCreateResponses.get(0);
            if (StringUtils.isNotBlank(orderAtomCreateResponse.getErrorCode())) {
                JSONObject features = JSON.parseObject(request.getFeatures());
                if (Objects.nonNull(features)
                        && Objects.nonNull(features.get(OrderFeaturesKey.ACTIVITY_SEQUENCE_NO))
                        && Objects.nonNull(features.get(OrderFeaturesKey.FORECAST_ORDER_LINE_ID_LIST))) {
                    sendMsgService.sendActivityFailMsg((String) features.get(OrderFeaturesKey.ACTIVITY_SEQUENCE_NO), (List<Long>) features.get(OrderFeaturesKey.FORECAST_ORDER_LINE_ID_LIST));
                }
                return Result.fail(orderAtomCreateResponse, orderAtomCreateResponse.getErrorCode(), orderAtomCreateResponse.getMessage());
            }

            return Result.success(orderAtomCreateResponse, "", "");
        } catch (Exception e) {
            StopWatchUtils.stop();
            log.error("SalesOrderDirectServiceImpl#create error", e);
            throw e;
        } finally {
            StopWatchUtils.print("SalesOrderDirectServiceImpl#create");
        }
    }

    @FacadeInvoker(value = "一盘货销售订单批量创建", errorCode = "OC-01-001-01-16-006")
    @Override
    public Result<SalesOrderBizCreateResponse> batchCreate(SalesOrderBizBatchCreateRequest request) {
        AssertUtils.isTrue(StringUtils.isBlank(request.getReqNo()), "OC-01-001-01-15-001", "请求编码");

        log.info("SalesOrderDirectServiceImpl#batchCreate request={}", JSON.toJSONString(request));
        String lockKey = SALES_ORDER_DIRECT_PREFIX + request.getReqNo();
        log.info("SalesOrderDirectServiceImpl#batchCreate lockKey={}", lockKey);

        try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!lock.lock()) {
                log.error("SalesOrderDirectServiceImpl#batchCreate 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }

            // 移除入参里的前后空格
            StopWatchUtils.start("订单中心直发订单批量创建", "removeSpace");
            TrimUtils.removeSpace(request);
            StopWatchUtils.stop();

            StopWatchUtils.start("订单中心直发订单批量创建", "paramsInvalidCheck");
            AssertUtils.lengthCheck(request.getReqNo(), 128, true, "OC-01-001-01-15-004", "请求编码");
            AssertUtils.isTrue(CollectionUtils.isEmpty(request.getOrderList()), "OC-01-001-01-15-001", "单据列表");
            request.getOrderList().forEach(order -> {
                if (StringUtils.isNotBlank(request.getFromSys())) {
                    order.setFromSys(request.getFromSys());
                }
                if (StringUtils.isNotBlank(request.getBusinessType())) {
                    order.setBusinessType(request.getBusinessType());
                }
                if (StringUtils.isNotBlank(request.getBusinessUnitCode())) {
                    order.setBusinessUnitCode(request.getBusinessUnitCode());
                }
                if (ObjectUtil.isNull(order.getIsSubmit())) {
                    order.setIsSubmit(Boolean.TRUE);
                }
                if (ObjectUtil.isNull(order.getCheckCreditB())) {
                    order.setCheckCreditB(Boolean.TRUE);
                }
                if (ObjectUtil.isNull(order.getCheckCredit())) {
                    order.setCheckCredit(Boolean.TRUE);
                }
                if (ObjectUtil.isNull(order.getCheckStock())) {
                    order.setCheckStock(Boolean.TRUE);
                }

                // 设置默认值
                order.setOrderCategoryCode(OrderCategoryEnum.STOCK.getCode());
            });
            salesOrderDirectBizCreateParamsCheck.paramsInvalidCheck(request.getOrderList(), new ArrayList<>());
            StopWatchUtils.stop();

            StopWatchUtils.start("订单中心直发订单批量创建", "createAsyncTask");
            String batchTaskId = asyncTaskCreateService.createAsyncTask(request.getFromSys() + "#" + request.getReqNo(),
                    request.getFromSys(), JSON.toJSONString(request), MessageTaskTypeEnum.OC_DIRECT_SALES_ORDER_BATCH_CREATE);
            StopWatchUtils.stop();

            SalesOrderBizCreateResponse salesOrderBizCreateResponse = new SalesOrderBizCreateResponse();
            salesOrderBizCreateResponse.setBatchTaskId(batchTaskId);
            return Result.success(salesOrderBizCreateResponse, "", "");
        } catch (Exception e) {
            StopWatchUtils.stop();
            log.error("SalesOrderDirectServiceImpl#batchCreate error", e);
            throw e;
        } finally {
            StopWatchUtils.print("SalesOrderDirectServiceImpl#batchCreate");
        }
    }

    @FacadeInvoker(value = "一盘货销售订单修改", errorCode = "OC-01-001-01-16-013")
    @Override
    public Result<OrderBizUpdateResponse> update(OrderBizUpdateRequest request) {
        log.info("SalesOrderDirectServiceImpl#update request={}", JSON.toJSONString(request));
        String lockKey = SALES_ORDER_DIRECT_PREFIX + request.getSalesOrderNo();
        log.info("SalesOrderDirectServiceImpl#update lockKey={}", lockKey);
        try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!lock.lock()) {
                log.error("SalesOrderDirectServiceImpl#update 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }

            // 移除入参里的前后空格
            StopWatchUtils.start("一盘货销售订单批量关闭", "removeSpace");
            TrimUtils.removeSpace(request);
            StopWatchUtils.stop();

            request.setOrderCategoryCode(OrderCategoryEnum.STOCK.getCode());
            OrderAtomUpdateResponse atomUpdateResponse = salesOrderBizUpdateService.update(request);

            OrderBizUpdateResponse bizUpdateResponse = new OrderBizUpdateResponse();
            BeanUtils.copyProperties(atomUpdateResponse, bizUpdateResponse);
            if (StringUtils.isNotBlank(bizUpdateResponse.getErrorCode())) {
                List<OrderLineAtomCreateResponse> orderDetails = atomUpdateResponse.getOrderDetails();
                if (CollectionUtils.isNotEmpty(orderDetails)) {
                    OrderLineAtomCreateResponse orderLineAtomCreateResponse = orderDetails.get(0);
                    return Result.fail(orderLineAtomCreateResponse.getErrorCode(), orderLineAtomCreateResponse.getMessage());
                }
                return Result.fail(atomUpdateResponse.getErrorCode(), atomUpdateResponse.getMessage());
            }

            // 发送MQ消息通知其他中心
            StopWatchUtils.start("订单中心商业修改", "sendSalesOrderChangeMsg");
            sendMsgService.sendSalesOrderChangeMsg(Lists.newArrayList(request.getSalesOrderNo()), InnerMessageEventEnum.SALES_ORDER_UPDATED);
            StopWatchUtils.stop();
            return Result.success(bizUpdateResponse, "", "");
        } catch (Exception e) {
            log.error("SalesOrderDirectServiceImpl#update error", e);
            throw e;
        } finally {
            StopWatchUtils.print("SalesOrderDirectServiceImpl#update");
        }
    }

    @Override
    @FacadeInvoker(value = "一盘货销售订单批量取消", errorCode = "OC-01-003-01-16-009")
    public Result<List<OrderAtomCancelResponse>> batchCancel(OrderAtomBatchCancelRequest request) {
        log.info("SalesOrderDirectServiceImpl#batchCancel request={}", JSON.toJSONString(request));
        String lockKey = SALES_ORDER_DIRECT_PREFIX + DigestUtils.md5Hex(JSON.toJSONString(request));
        log.info("SalesOrderDirectServiceImpl#batchCancel lockKey={}", lockKey);

        try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!lock.lock()) {
                log.error("SalesOrderDirectServiceImpl#batchCancel 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }

            // 移除入参里的前后空格
            StopWatchUtils.start("一盘货销售订单批量取消", "removeSpace");
            TrimUtils.removeSpace(request);
            StopWatchUtils.stop();

            List<OrderAtomCancelResponse> responseList = selesOrderAtomCancelService.batchCancel(request, OrderCategoryEnum.STOCK.getCode());
            responseList.forEach(response -> {
                if (Objects.isNull(response.getSuccess())) {
                    response.setSuccess(Boolean.FALSE);
                }
            });

            // 发送MQ消息通知其他中心
//            List<String> salesOrderNos = responseList.stream()
//                    .filter(OrderAtomCancelResponse::getSuccess)
//                    .map(OrderAtomCancelResponse::getSalesOrderNo)
//                    .collect(Collectors.toList());
//            sendMsgService.sendSalesOrderChangeMsg(salesOrderNos, InnerMessageEventEnum.SALES_ORDER_UPDATED);

            return Result.success(responseList, "", "");
        } catch (Exception e) {
            log.error("SalesOrderDirectServiceImpl#batchCancel error", e);
            throw e;
        } finally {
            StopWatchUtils.print("SalesOrderDirectServiceImpl#batchCancel");
        }
    }

    @FacadeInvoker(value = "一盘货销售订单批量关闭", errorCode = "OC-01-003-01-16-003")
    @Override
    public Result<List<OrderAtomCloseResponse>> batchClose(OrderBizBatchCloseRequest request) {
        log.info("SalesOrderDirectServiceImpl#batchClose request={}", JSON.toJSONString(request));
        String lockKey = SALES_ORDER_DIRECT_PREFIX + DigestUtils.md5Hex(JSON.toJSONString(request));
        log.info("SalesOrderDirectServiceImpl#batchClose lockKey={}", lockKey);

        try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!lock.lock()) {
                log.error("SalesOrderDirectServiceImpl#batchClose 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }

            // 移除入参里的前后空格
            StopWatchUtils.start("一盘货销售订单批量关闭", "removeSpace");
            TrimUtils.removeSpace(request);
            StopWatchUtils.stop();

            request.setOrderCategoryCode(OrderCategoryEnum.STOCK.getCode());
            Result<List<OrderAtomCloseResponse>> result = salesOrderGroupCloseService.batchClose(request);
            return result;
        } catch (Exception e) {
            log.error("SalesOrderDirectServiceImpl#batchClose error", e);
            throw e;
        } finally {
            StopWatchUtils.print("SalesOrderDirectServiceImpl#batchClose");
        }
    }

    @Override
    @FacadeInvoker(value = "一盘货销售订单批量提交", errorCode = "OC-01-003-01-16-002")
    public Result<List<OrderAtomSubmitResponse>> batchSubmit(OrderBizBatchSubmitRequest request) {
        log.info("SalesOrderDirectServiceImpl#batchSubmit request={}", JSON.toJSONString(request));
        String lockKey = SALES_ORDER_DIRECT_PREFIX + DigestUtils.md5Hex(JSON.toJSONString(request));
        log.info("SalesOrderDirectServiceImpl#batchSubmit lockKey={}", lockKey);

        try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!lock.lock()) {
                log.error("SalesOrderDirectServiceImpl#batchSubmit 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }

            // 移除入参里的前后空格
            StopWatchUtils.start("一盘货销售订单批量提交", "removeSpace");
            TrimUtils.removeSpace(request);
            StopWatchUtils.stop();

            for (OrderAtomSubmitRequest salesOrder : request.getOrderList()) {
                if (Objects.isNull(salesOrder.getCheckStock())) {
                    salesOrder.setCheckStock(Boolean.TRUE);
                }
                if (Objects.isNull(salesOrder.getCheckCredit())) {
                    salesOrder.setCheckCredit(Boolean.TRUE);
                }
                if (Objects.isNull(salesOrder.getCheckCreditB())) {
                    salesOrder.setCheckCreditB(Boolean.TRUE);
                }
            }
            request.setOrderCategoryCode(OrderCategoryEnum.STOCK.getCode());

            List<OrderAtomSubmitResponse> resp = salesOrderBizSubmitService.batchSubmit(request);

            if (CollectionUtils.isNotEmpty(resp)) {
                StopWatchUtils.start("一盘货销售订单批量提交", "sendMsgToSendKafka");
                // 发送消息通知来源系统
                List<PushOrderInfoToMnSideRequestOrderInfo> pushOrderInfoList = new ArrayList<>();
                for (OrderAtomSubmitResponse submitResponse : resp) {
                    pushOrderInfoList.add(PushOrderInfoToMnSideRequestOrderInfo.builder()
                            .salesOrderNo(submitResponse.getSalesOrderNo())
                            .orderStatus(SalesOrderPushStatusEnum.FAIL_UPDATE.getOrderStatusCode())
                            .message(submitResponse.getMessage())
                            .build());
                }
                CommonAsyncMessageResponse commonAsyncMessageResponse = new CommonAsyncMessageResponse();
                commonAsyncMessageResponse.setEventCode(AsyncMessageEventEnum.SALES_ORDER_UPDATE.getValue());
                commonAsyncMessageResponse.setEventName(AsyncMessageEventEnum.SALES_ORDER_UPDATE.getLabel());
                commonAsyncMessageResponse.setEventTime(String.valueOf(new Date().getTime()));
                commonAsyncMessageResponse.setFromSys(request.getFromSys());
                commonAsyncMessageResponse.setBusinessUnitCode(request.getBusinessUnitCode());
                commonAsyncMessageResponse.setData(pushOrderInfoList);
                sendMsgService.sendMsgToSendKafka(commonAsyncMessageResponse);
                log.info("SalesOrderDirectServiceImpl#batchSubmit sendMsgToSendKafka message={}", commonAsyncMessageResponse);
                StopWatchUtils.stop();
            }
            log.info("SalesOrderDirectServiceImpl#batchSubmit finish function resp={}", JSON.toJSONString(resp));
            return Result.success(resp, "", "");
        } catch (Exception e) {
            log.error("SalesOrderDirectServiceImpl#batchSubmit error", e);
            throw e;
        } finally {
            StopWatchUtils.print("SalesOrderDirectServiceImpl#batchSubmit");
        }
    }
}
